#include<iostream>
#include<unordered_map>
#include<algorithm>
using namespace std;
//对于这种每个数都很大但是数的数量很小的问题我们进行离散化
const int N = 1e5 + 10;
struct Node
{
	int i;
	int j;
	int e;
}a[N];//因为不止一个数，所以得用结构体
unordered_map<int, int> mp;
int t;
int n;
int pos;
int dist[N * 2];//注意空间别开小了
int fa[N*2];
int find(int x)
{
	if (fa[x] == x) return x;
	else return fa[x] = find(fa[x]);
}
void un(int x, int y)
{
	//注意下面这一句不要写错。经常写错
	int fx = find(x);int fy = find(y);//找爹
	if (fx != fy)
	{
		fa[fx] = fy;
	}
}
int main()
{
	cin >> t;
	while (t--)
	{
		pos = 0;
		mp.clear();
		//注意，dist和fa不用清空因为后面会覆盖的
		//多组数据问题一定要考虑是否清空数据
		cin >> n;
		for (int i = 1;i <= n;i++)
		{
			cin >> a[i].i >> a[i].j >> a[i].e;
			dist[++pos] = a[i].i;dist[++pos] = a[i].j;
		}
		sort(dist + 1, dist +pos+1);
		//分配下标
		//查重
		int p = 0;
		for (int i = 1;i <= pos;i++)
		{
			int x = dist[i];
			if (mp.count(x)) continue;
			p++;
			mp[x] = p;
		}

		//并查集初始化
		for (int i = 1;i <= p;i++) fa[i] = i;

		int flag = 1;
		//操作
		//把相等的信息都维护起来
		for (int i = 1;i <= n;i++)
		{
			if (a[i].e == 1)
			{
				un(mp[a[i].i], mp[a[i].j]);//注意这里存的是下标
			}
		}
		//注意判断和插入循环一定要分开，不能是一个循环
		for (int i = 1;i <= n;i++)
		{
			if (a[i].e == 0)
			{
				//看看是不是一个爹
				//注意这里传入的一定是下标，别把值穿进去了
				int fx = find(mp[a[i].i]);
				int fy = find(mp[a[i].j]);
				if (fx == fy)
				{
					cout << "NO" << endl;
					flag = 0;
					break;
				}
			}
		}
		if (flag == 1) cout << "YES" << endl;
	}
	return 0;
}